Skip to content

Commit 637d985

Browse files
committed
vm_domainset: Refactor iterators, multiple fixes
vm_domainset_iter_first() would not check if the initial domain selected by the policy was effectively valid (i.e., allowed by the domainset and not marked as ignored by vm_domainset_iter_ignore()). It would just try to skip it if it had less pages than 'free_min', and would not take into account the possibility of no domains being valid. Factor out code that logically belongs to the iterator machinery and is not tied to how allocations (or impossibility thereof) are to be handled. This allows to remove duplicated code between vm_domainset_iter_page() and vm_domainset_iter_policy(), and between vm_domainset_iter_page_init() and _vm_domainset_iter_policy_init(). This also allows to remove the 'pages' parameter from vm_domainset_iter_page_init(). This also makes the two-phase logic clearer, revealing an inconsistency between setting 'di_minskip' to true in vm_domainset_iter_init() (implying that, in the case of waiting allocations, further attempts after the first sleep should just allocate for the first domain, regardless of their situation with respect to their 'free_min') and trying to skip the first domain if it has too few pages in vm_domainset_iter_page_init() and _vm_domainset_iter_policy_init(). Fix this inconsistency by resetting 'di_minskip' to 'true' in vm_domainset_iter_first() instead so that, after each vm_wait_doms() (waiting allocations that could not be satisfied immediately), we again start with only the domains that have more than 'free_min' pages. While here, fix the minor quirk that the round-robin policy would start with the domain after the one pointed to by the initial value of 'di_iter' (this just affects the case of resetting '*di_iter', and would not cause domain skips in other circumstances, i.e., for waiting allocations that actually wait or at each subsequent new iterator creation with same iteration index storage). PR: 277476 Tested by: Kenneth Raplee <kenrap_kennethraplee.com> Fixes: 7b11a48 ("Add files for r327895") Fixes: e5818a5 ("Implement several enhancements to NUMA policies.") Fixes: 23984ce ("Avoid resource deadlocks when one domain has exhausted its memory."...) MFC after: 10 days Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D51251
1 parent d0b691a commit 637d985

File tree

7 files changed

+181
-122
lines changed

7 files changed

+181
-122
lines changed

sys/kern/kern_malloc.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -751,11 +751,14 @@ malloc_domainset(size_t size, struct malloc_type *mtp, struct domainset *ds,
751751
return (malloc_large(size, mtp, DOMAINSET_RR(), flags
752752
DEBUG_REDZONE_ARG));
753753

754-
vm_domainset_iter_policy_init(&di, ds, &domain, &flags);
755-
do {
756-
va = malloc_domain(&size, &indx, mtp, domain, flags);
757-
} while (va == NULL && vm_domainset_iter_policy(&di, &domain) == 0);
754+
indx = -1;
755+
va = NULL;
756+
if (vm_domainset_iter_policy_init(&di, ds, &domain, &flags) == 0)
757+
do {
758+
va = malloc_domain(&size, &indx, mtp, domain, flags);
759+
} while (va == NULL && vm_domainset_iter_policy(&di, &domain) == 0);
758760
malloc_type_zone_allocated(mtp, va == NULL ? 0 : size, indx);
761+
759762
if (__predict_false(va == NULL)) {
760763
KASSERT((flags & M_WAITOK) == 0,
761764
("malloc(M_WAITOK) returned NULL"));

sys/vm/uma_core.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4017,8 +4017,9 @@ keg_fetch_slab(uma_keg_t keg, uma_zone_t zone, int rdomain, const int flags)
40174017
rr = rdomain == UMA_ANYDOMAIN;
40184018
if (rr) {
40194019
aflags = (flags & ~M_WAITOK) | M_NOWAIT;
4020-
vm_domainset_iter_policy_ref_init(&di, &keg->uk_dr, &domain,
4021-
&aflags);
4020+
if (vm_domainset_iter_policy_ref_init(&di, &keg->uk_dr, &domain,
4021+
&aflags) != 0)
4022+
return (NULL);
40224023
} else {
40234024
aflags = flags;
40244025
domain = rdomain;
@@ -5245,8 +5246,9 @@ uma_prealloc(uma_zone_t zone, int items)
52455246
slabs = howmany(items, keg->uk_ipers);
52465247
while (slabs-- > 0) {
52475248
aflags = M_NOWAIT;
5248-
vm_domainset_iter_policy_ref_init(&di, &keg->uk_dr, &domain,
5249-
&aflags);
5249+
if (vm_domainset_iter_policy_ref_init(&di, &keg->uk_dr, &domain,
5250+
&aflags) != 0)
5251+
panic("%s: Domainset is empty", __func__);
52505252
for (;;) {
52515253
slab = keg_alloc_slab(keg, zone, domain, M_WAITOK,
52525254
aflags);

0 commit comments

Comments
 (0)